
#ifndef TEXESFERA_H_
#define TEXESFERA_H_

#include <assert.h>
#include <cmath>
#include <GL/gl.h> 

#include "cubo.h"
#include "config.h"

class TexturaEsferas {
   private:
      TexturaEsferas(const TexturaEsferas &aCopiar);
      const TexturaEsferas& operator=(const TexturaEsferas &aCopiar);

      Config config;
      CuboDeEsferas esferas;

      GLuint id;


      inline unsigned int at(unsigned int profundidad,  unsigned int fila, 
            unsigned int columna) const {

         unsigned int resolucion = config.resolucion();
         assert(resolucion > 0);

         unsigned int pos = columna + (fila*resolucion) + (profundidad*pow(resolucion,2));

         assert( pos < pow(resolucion, 3) );
         return pos;
      }

      void generarTextura() {

         unsigned int resolucion = config.resolucion();

         glGenTextures(1, &id);
         
         glBindTexture(GL_TEXTURE_3D, id);

         glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
         glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	 glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);

	 glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	 glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	
         Voxel *tex = new Voxel[resolucion*resolucion*resolucion];

         for(unsigned int i = 0; i < resolucion; ++i){
            for(unsigned int j = 0; j < resolucion; ++j){
               for(unsigned int k = 0; k < resolucion; ++k){
                  esferas.getColorVoxel( k, j, i, tex[at(i, j, k)]);
               }
            }
         }

         glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 
               resolucion, resolucion, resolucion,
               0, GL_RGBA, GL_FLOAT, tex);

         
         delete[] tex;
      }


   public:

      TexturaEsferas() {}
  
      inline unsigned int cantPlanos() const { return config.cantPlanos(); }

      void fromArchivo(const char *nombre) {
         assert(nombre != 0);

         esferas.limpiar();
         config.fromArchivo(nombre, esferas);

         assert(config.resolucion() > 0);

         generarTextura();
      }

      inline void enlazar() const {
         glBindTexture(GL_TEXTURE_3D, id);
      }

};

#endif
